#define NOMINMAX
#include "TreasuryFuturesChartElement.h"
#include "../data/TreasuryFuturesData.h"
#include <QPoint>
#include "tfbondlib/BondFuture.h"
#include "bondlib/RealTimeDeal/BondMarketStreamV2.h"
#include "core/StyleMgr.h"

#define  FIXED_CHART_MAX_LINE 10

void CFixedFutureChartBorder::drawElement(QStylePainter* painter, const QRect& rcRct, int nCurPt, QWidget* pParent )
{
	if (!painter) return;
	if (rcRct.width()<10 || rcRct.height()<10) return;

	painter->save();
	QColor clrBorder(38, 55, 53);
	QColor clrBackArray(23, 36, 34);

	int nHorCount = 4, nVecCount = 7;
	int nHortGap = rcRct.width() / nVecCount; //横坐标
	int nVecGap = rcRct.height() / nHorCount;
	for (int nF = 0; nF < nVecCount; nF++){
		QRect rcFill;
		rcFill.setTopLeft(QPoint(rcRct.left() + nF * nHortGap, rcRct.top()));
		rcFill.setBottomRight(QPoint(rcRct.left() + (nF + 1) * nHortGap, rcRct.bottom()));
		if (nF == nVecCount - 1) rcFill.setRight(rcRct.right()-1);
		painter->fillRect(rcFill, clrBackArray);
	}

	QPen pen(clrBorder, 1);
	painter->setPen(pen);
	for (int nRow = 0; nRow <= nHorCount; nRow++){
		QPoint pt1 = QPoint(rcRct.left(), rcRct.top() + nRow * nVecGap);
		QPoint pt2 = QPoint(rcRct.right(), rcRct.top() + nRow * nVecGap);
		if (nRow == nHorCount) {
			pt1.setY(rcRct.bottom() - 1);
			pt2.setY(rcRct.bottom() - 1);
		}
		painter->drawLine(pt1.x(), pt1.y(), pt2.x(), pt2.y());
	}

	for (int nCol = 1; nCol <= nVecCount - 1; nCol++){
		QPoint pt1 = QPoint(rcRct.left() + nCol * nHortGap, rcRct.top());
		QPoint pt2 = QPoint(rcRct.left() + nCol * nHortGap, rcRct.bottom());
		if (nCol == nVecCount) {
			pt1.setX(rcRct.right()-1);
			pt2.setX(rcRct.right()-1);
		}
		painter->drawLine(pt1.x(), pt1.y(), pt2.x(), pt2.y());
	}
	painter->restore();
}

void CFixedFutureChartLineBase::drawElement(QStylePainter* painter, const QRect& rcRct, int nCurPt, QWidget* pParent)
{
	if (rcRct.width() < 10 || rcRct.height() < 10) return;
	CFixedNatFutureTFData tfData(false);
	if (!m_pData || !m_pData->GetCurrentData(tfData))  return;
	CFixedNatWholeParam par;
	tfData.LoadWholeParam(par, !m_bToday);
	std::map<int, CFixedNatFuturePoint>& mapPoint = m_bToday ? tfData.m_mapPoint : tfData.m_mapPointYes;
	int nDataSz = mapPoint.size();
	int nCount = nDataSz;
	if (nCount <= 0 || nDataSz <= 0) return;
	double dbPrc, dbHorGap = rcRct.width() / (double)nDataSz;
	double dbMax = 0.0f, dbMin = 0.0f;
	QColor crLine = StyleMgr::instance().color("Highlight"), crOn = StyleMgr::instance().color("Highlight");
	if (m_nChartType == FDraw_PrcLine){
		dbMax = par.m_dbMaxPrc, dbMin = par.m_dbMinPrc;
	}
	else if (m_nChartType == FDraw_InteLine){
		crLine = QColor(0, 154, 255), crOn = QColor(0, 154, 255);
		dbMax = par.m_dbMaxOpenIn, dbMin = par.m_dbMinOpenIn;
	}
	else return;

	if (dbMax > 0.001 &&  dbMin > 0.001){
		double dbAdd = (dbMax - dbMin)* 0.1;
		dbMax += dbAdd;
		dbMin -= dbAdd;
		dbMin = std::max(dbMin, 0.);
	}
	else return;

	double dbVctGap = rcRct.height();
	if (dbMax - dbMin > 0.001)   dbVctGap = rcRct.height() / (dbMax - dbMin);
	std::map<int, CFixedNatFuturePoint>::const_iterator itr = mapPoint.begin();
	int nLoop = 0, nRealLoop = 0, nFillMin = 6, nFillMax = 12;
	bool bCurrent = false, bOnLine = false;
	QRect rcCurrent;
	QPoint ptMouse = QPoint(-1000,-1000); 
	if (pParent){
		int x = pParent->mapFromGlobal(QCursor().pos()).x();
		int y = pParent->mapFromGlobal(QCursor().pos()).y();
		ptMouse.setX(x);
		ptMouse.setY(y);
	}
	int nGapTips = 3;
	for (; itr != mapPoint.end() && nCount> 0; itr++, nCount--, nRealLoop++){
		if (nLoop >= FIXED_NAT_ELE_POINT_MAX){
			//LOGINFO("fixed nat future chart line : %d Over max point",m_nChartType);
			//SASSERTS(0, "fixed nat future chart line Over max point!");
			break;
		}
		if (m_nChartType == FDraw_PrcLine) dbPrc = itr->second.m_fPrice;
		else if (m_nChartType == FDraw_InteLine) dbPrc = itr->second.m_dbOpenInt;
		if (dbPrc > 0.001){
			int x = rcRct.left() + nRealLoop * dbHorGap;
			int y = rcRct.bottom() - dbVctGap * (dbPrc - dbMin);
			m_pointArr[nLoop].setX(x);
			m_pointArr[nLoop].setY(y);
			if (fabs(m_pointArr[nLoop].x() - ptMouse.x()) < nGapTips && fabs(m_pointArr[nLoop].y() - ptMouse.y()) < nGapTips) {
				bOnLine = true;
			}
			if (itr->first == nCurPt) {
				bCurrent = true;
				rcCurrent = QRect(QPoint(m_pointArr[nLoop].x()-nFillMin/2, m_pointArr[nLoop].y()-nFillMin/2), QPoint(m_pointArr[nLoop].x()+nFillMin/2, m_pointArr[nLoop].y()+nFillMin/2));
			}
			nLoop++;
		}
		else if (m_nChartType != FDraw_InteLine) break;
	}

	painter->save();
	QPen pen(QBrush(bOnLine?crOn:crLine), bOnLine?2:1);
	painter->setPen(pen);
	painter->setRenderHint(QPainter::Antialiasing);
	painter->drawPolyline(&m_pointArr[0], nLoop);
	if (bCurrent){
		QRect rcMax = rcCurrent;
		int nInf = (nFillMax - nFillMin) / 2;
		painter->setBrush(QBrush(NAME_COLOR("MainTitleBack")));
		painter->drawEllipse(rcMax);
		painter->setBrush(QBrush(bOnLine ? crOn : crLine));
		rcCurrent.adjust(nInf, nInf, -nInf, -nInf);
		painter->drawEllipse(rcCurrent);
	}
	painter->restore();
}

void CFixedFutureChartBar::drawElement(QStylePainter* painter, const QRect& rcRct, int nCurPt, QWidget* pParent)
{
	if (!painter) return;
	if (rcRct.width()<10 || rcRct.height()<10) return;

	CFixedNatFutureTFData tfData(false);
	if (!m_pData || !m_pData->GetCurrentData(tfData)) return;
	CFixedNatWholeParam par;
	tfData.LoadWholeParam(par, !m_bToday);
	std::map<int, CFixedNatFuturePoint>& mapPoint = m_bToday ? tfData.m_mapPoint : tfData.m_mapPointYes;
	int nDataSz = mapPoint.size();
	int nCount = nDataSz;
	if (nCount <= 0 || nDataSz <= 0) return;
	double dbHorGap = rcRct.width() / (double)nDataSz;
	double dbMax = par.m_dbMaxVol, dbMin = par.m_dbMinVol;
	dbMax += (dbMax - dbMin) * 0.05;
	if (dbMax - dbMin < 0.01) dbMax += 1;
	double dbVctGap = rcRct.height() / (dbMax - dbMin);
	if (dbMax > 0.001){
		double dbAdd = (dbMax - dbMin)* 0.1;
		dbMax += dbAdd;
		dbMin = std::max(dbMin, 0.);
	}
	else return;

	int nVol; QRect rcTemp;
	int nValidCount = std::min(nCount, (int)mapPoint.size());
	std::map<int, CFixedNatFuturePoint>::const_iterator itr = mapPoint.begin();
	int nLoop = 0;
	QColor clrBar(120, 70, 250);
	QColor clrTrans(51, 120, 70);

	painter->save();
	for (; itr != mapPoint.end() && nCount > 0; itr++, nCount--, nLoop++){
		if (nLoop >= FIXED_NAT_ELE_POINT_MAX){
			//LOGINFO("fixed nat future chart bar Over max point");
			//SASSERTS(0, "fixed nat future chart bar Over max point!");
			break;
		}
		nVol = itr->second.m_nVolum;
		if (itr->second.m_fPrice < 1)break;
		if (nVol > 0){
			rcTemp.setLeft(rcRct.left() + (nLoop)*dbHorGap);
			rcTemp.setTop(rcRct.bottom() - (nVol - dbMin) * dbVctGap);
			rcTemp.setRight(rcRct.left() + (nLoop + 1) * dbHorGap);
			rcTemp.setBottom(rcRct.bottom());
			painter->fillRect(rcTemp, nCurPt == nLoop ? clrTrans : clrBar);
		}
	}
	painter->restore();
}

CFixedFutureChartTime::CFixedFutureChartTime()
{
	m_nChartType = FDraw_Time;
	m_clrXpos = StyleMgr::instance().color("SupportingWord");
	buildXPosTxt();
}

void CFixedFutureChartTime::drawElement(QStylePainter* painter, const QRect& rcRct, int nCurPt, QWidget* pParent)
{
 	if (!painter) return;
 	if (rcRct.width() < 10 || rcRct.height() < 10) return;
 
 	int nPointSz = m_mapFixedTxt.size();
 	if (nPointSz <= 0) return;

 	double dbGap = rcRct.width() / (float)(FIXED_NAT_ELE_POINT_MAX -1);
 	int nPoint, nRight = -1, nMinGap = 8;
 	QString strTemp;
 	QRectF rfMes;
 	QRect rcDraw = rcRct;
 
	painter->save();
 	for (std::map<int, QString>::const_iterator itr = m_mapFixedTxt.begin(); itr != m_mapFixedTxt.end(); itr++){
 		strTemp = itr->second;
 		nPoint = rcRct.left() + itr->first * dbGap;

		QFontMetrics fm = painter->fontMetrics();
		int w = fm.width(strTemp);
 		rcDraw.setLeft(nPoint - w / 2);
		rcDraw.setRight(nPoint + w / 2 + nMinGap);
		if (rcDraw.left() < rcRct.left()){
			//rcDraw += QPoint(rcRct.left() - rcDraw.left(), 0);
			rcDraw.moveLeft(rcRct.left() - rcDraw.left());
		}
		if (rcDraw.right() > rcRct.right()) {
			//rcDraw -= QPoint(rcDraw.right() - rcRct.right(), 0);
			rcDraw.moveRight(rcDraw.right() - rcRct.right());
		}
		if (rcDraw.left() <= nRight) continue;
		nRight = rcDraw.right();
		painter->drawText(rcDraw, strTemp);
 	}
	painter->restore();
}

void CFixedFutureChartTime::buildXPosTxt()
{
	m_mapFixedTxt.clear();
	int nStart = 1;
	int nHour = 9, nMin = 15;
	int nMinBegin = 30, nMinEnd = 15;
	//int nMinBegin = 15, nMinEnd = 15;
	//int nBeginDate = (int)CBondFuture::instance().GetChangeDate();
	//int nCurDate = CMarketStream::GetBondDealInvalidateDay();
	//if (nBeginDate > 0 && nBeginDate <= nCurDate){
	//nMinBegin = 30;
	//}

	nMin = nMinBegin;
 	QString strTime;
	while (nStart < FIXED_NAT_ELE_POINT_MAX){
		if (nMin % 15 == 0){
			strTime = QString::asprintf("%02d:%02d", nHour, nMin);
			m_mapFixedTxt[nStart] = strTime;
		}
		if (nHour == 11 && nMin == 30){
			nHour = 13;
			nMin = 0;
		}
		else if (nMin == 59){
			nHour++;
			nMin = 0;
		}
		else nMin++;
		if (nHour == 15 && nMin == nMinEnd) break;
		nStart++;
	}
}
